<template>
  <div class="menu-page">
    <!-- 搜索栏 -->
    <el-card class="filter-card">
      <el-form :inline="true" :model="query">
        <el-form-item label="菜单名称">
          <el-input v-model="query.menuName" placeholder="请输入菜单名称" clearable style="width: 200px"/>
        </el-form-item>
        <el-form-item label="状态">
          <el-select v-model="query.menuFlag" placeholder="请选择" clearable style="width: 200px">
            <el-option label="启用" :value="'0'" />
            <el-option label="禁用" :value="'1'" />
          </el-select>
        </el-form-item>
<!--        <el-form-item label="菜单类型">-->
<!--          <el-select v-model="query.menuType" placeholder="请选择" clearable style="width: 120px">-->
<!--            <el-option label="目录" :value="'D'" />-->
<!--            <el-option label="菜单" :value="'M'" />-->
<!--            <el-option label="按钮" :value="'B'" />-->
<!--          </el-select>-->
<!--        </el-form-item>-->
        <el-form-item>
          <el-button type="primary" @click="handleSearch">搜索</el-button>
          <el-button @click="handleReset">重置</el-button>
        </el-form-item>
      </el-form>
    </el-card>

    <!-- 树形表格 -->
    <el-card>
      <el-table
        ref="tableRef"
        :data="tableData"
        style="width: 100%"
        row-key="menuId"
        v-loading="loading"
        :tree-props="{ children: 'subMenus', hasChildren: 'hasChildren' }"
        @expand-change="handleExpandChange"
        :expand-row-keys="expandedKeys"
      >

        <el-table-column prop="menuName" label="菜单名" width="200">
          <template #default="scope">
            <!-- 移除手动添加的图标，使用表格自带的展开/折叠图标 -->
            <span class="tree-indent" :style="{ paddingLeft: `${(scope.row.level - 1) * 1}px` }">
              {{ scope.row.menuName }}
            </span>
          </template>
        </el-table-column>
        <!-- 其他列保持不变 -->
        <el-table-column prop="icon" label="图标">
          <template #default="{ row }">
            <el-icon v-if="row.icon"><component :is="row.icon" /></el-icon>
          </template>
        </el-table-column>
        <el-table-column prop="orderNum" label="排序" sortable />
        <el-table-column prop="path" label="组件路径" show-overflow-tooltip />
        <el-table-column prop="permission" label="权限标识" width="210"/>
        <el-table-column prop="menuFlag" label="状态">
          <template #default="{ row }">
            <el-tag :type="row.menuFlag === '0' ? 'success' : 'danger'">
              {{ row.menuFlag === '0' ? '启用' : '禁用' }}
            </el-tag>
          </template>
        </el-table-column>

        <!-- 操作列 -->
        <el-table-column label="操作" width="300">
          <template #default="{ row }">
            <el-button size="small" type="success" @click="handleAdd(row)">新增子菜单</el-button>
            <el-button size="small" type="primary" @click="handleEdit(row)">修改</el-button>
            <el-popconfirm title="确定删除吗？" @confirm="handleDelete(row.menuId)">
              <template #reference>
                <el-button size="small" type="danger">删除</el-button>
              </template>
            </el-popconfirm>
          </template>
        </el-table-column>
      </el-table>
    </el-card>

    <!-- 新增/编辑弹窗 保持不变 -->
    <el-dialog v-model="dialogVisible" :title="dialogTitle" width="500px">
      <el-form ref="menuFormRef" :model="menuForm" :rules="rules" label-width="100px">
        <el-form-item label="菜单名称" prop="menuName">
          <el-input v-model="menuForm.menuName" placeholder="请输入菜单名称" />
        </el-form-item>
        <el-form-item label="父菜单" prop="parentId">
          <el-select v-model="menuForm.parentId" placeholder="请选择父菜单">
            <el-option :value="'0'" label="根菜单" />
            <el-option v-for="menu in menuTree" :key="menu.menuId" :label="menu.menuName" :value="menu.menuId" />
          </el-select>
        </el-form-item>
        <el-form-item label="菜单类型" prop="menuType">
          <el-select v-model="menuForm.menuType" placeholder="请选择菜单类型">
            <el-option label="目录" :value="'D'" />
            <el-option label="菜单" :value="'M'" />
            <el-option label="按钮" :value="'B'" />
          </el-select>
        </el-form-item>
        <el-form-item label="排序" prop="orderNum">
          <el-input v-model.number="menuForm.orderNum" placeholder="请输入排序号" />
        </el-form-item>
<!--        <el-form-item label="图标">-->
<!--          <el-input v-model="menuForm.icon" placeholder="请输入图标组件名" />-->
<!--        </el-form-item>-->
        <el-form-item label="图标" prop="icon">
          <IconSelector v-model="menuForm.icon" placeholder="请选择菜单图标"/>
        </el-form-item>
        <el-form-item label="路由名称">
          <el-input v-model="menuForm.routerName" placeholder="请输入路由名称" />
        </el-form-item>
        <el-form-item label="路由地址" v-if="menuForm.menuType !== 'B'">
          <el-input v-model="menuForm.path" placeholder="请输入路由地址" />
        </el-form-item>
        <el-form-item label="组件路径" v-if="menuForm.menuType === 'M'">
          <el-input v-model="menuForm.component" placeholder="请输入组件路径" />
        </el-form-item>
        <el-form-item label="权限标识">
          <el-input v-model="menuForm.permission" placeholder="请输入权限标识" />
        </el-form-item>
        <el-form-item label="状态" prop="menuFlag">
          <el-select v-model="menuForm.menuFlag">
            <el-option label="启用" :value="'0'" />
            <el-option label="禁用" :value="'1'" />
          </el-select>
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" @click="handleSubmit" :loading="formLoading">确定</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
// 脚本部分保持不变
import { onMounted, reactive, ref, watch,nextTick } from 'vue'
import type { FormInstance, TableInstance } from 'element-plus'
import { ElMessage, ElMessageBox, FormRules } from 'element-plus'
import { ArrowDown, ArrowRight, Plus, Edit, Delete} from '@element-plus/icons-vue'
import { getMenuList, getMenuById, addMenu, updateMenu, deleteMenu, getMenuTree } from '@/api/menu'
import IconSelector from './IconSelector.vue';
import { iconNames } from './icon';
import useLoginStore from "@/stores/login"; // 导入图标名称列表用于验证


// 类型定义
interface Menu {
  menuId: string
  menuName: string
  parentId: string
  path: string
  component: string
  permission: string
  menuType: 'D' | 'M' | 'B'
  icon: string
  orderNum: number
  menuFlag: '0' | '1'
  routerName?: string
  subMenus?: Menu[]
  level: number
  hasChildren?: boolean
}

const tableRef = ref<TableInstance>()  // 添加这行

// 表格相关

const multipleSelection = ref<Menu[]>([])
const tableData = reactive<Menu[]>([])
const loading = ref(false)

// 展开的节点ID集合
const expandedKeys = ref<(number | string)[]>([])

// 搜索表单
const query = reactive({
  menuName: '',
  menuFlag: '',
  menuType: ''
})

// 弹窗相关
const dialogVisible = ref(false)
const dialogTitle = ref('新增菜单')
const dialogType = ref<'add' | 'edit'>('add')
const menuFormRef = ref<FormInstance>()
const formLoading = ref(false)
const menuForm = reactive<Menu>({
  menuId: '',
  menuName: '',
  parentId: '0',
  path: '',
  component: '',
  permission: '',
  menuType: 'M',
  icon: '',
  orderNum: 0,
  menuFlag: '0',
  level: 1
})

// 菜单树
const menuTree = ref<Menu[]>([])

// 检查节点是否展开
const isExpanded = (menuId: number | string) => {
  return expandedKeys.value.includes(menuId)
}

// 页面挂载时加载数据 - 默认只展开一级节点
onMounted(() => {
  getMenusByCondition()
  loadMenuTree()
})

// 获取菜单列表
const getMenusByCondition = () => {
  loading.value = true
  const params = { ...query }

  return getMenuList(params).then(res => {
    const { list } = res.data
    const treeData = buildTree(list, '0')
    const processedData = processTreeData(treeData, 1)

    tableData.length = 0
    tableData.push(...processedData)
  }).catch(error => {
    ElMessage.error('查询失败: ' + error.message)
  }).finally(() => {
    loading.value = false
  })
}

// 构建树形结构
const buildTree = (list: Menu[], parentId: number | string): Menu[] => {
  const targetParentId = String(parentId)
  return list
    .filter(item => String(item.parentId) === targetParentId)
    .map(item => {
      const children = buildTree(list, item.menuId)
      return {
        ...item,
        subMenus: children.length > 0 ? children : undefined,
        hasChildren: children.length > 0,
        level: 0
      }
    })
}

// 处理树形数据层级 - 强化level字段准确性
const processTreeData = (tree: Menu[], level: number): Menu[] => {
  return tree.map(item => {
    const processedItem = {
      ...item,
      level: level, // 明确设置层级
      hasChildren: item.subMenus && item.subMenus.length > 0
    };
    if (processedItem.subMenus && processedItem.subMenus.length > 0) {
      processedItem.subMenus = processTreeData(processedItem.subMenus, level + 1);
    }
    return processedItem;
  });
};

// 处理节点展开/折叠事件 - 全新实现
const handleExpandChange = (row: Menu, expanded: boolean) => {
  const currentMenuId = String(row.menuId);

  if (expanded) {
    // 展开时添加当前节点ID
    if (!expandedKeys.value.includes(currentMenuId)) {
      expandedKeys.value = [...expandedKeys.value, currentMenuId];
    }
  } else {
    // 折叠时移除当前节点ID
    expandedKeys.value = expandedKeys.value.filter(id => {return String(id) !== currentMenuId;});

  }

  // 3. 修复重绘时机：必须用nextTick等待expandedKeys更新完成，再让表格重绘
  nextTick(() => {
    if (tableRef.value) {
      tableRef.value.doLayout();
      // 打印日志验证：折叠后应能看到expandedKeys中移除了当前节点ID
      console.log('折叠后expandedKeys:', expandedKeys.value);
    }
  });
};




// 加载菜单树
const loadMenuTree = () => {
  getMenuTree().then(res => {
    menuTree.value = res.data
  }).catch(error => {
    ElMessage.error('加载菜单树失败: ' + error.message)
  })
}

// 打开新增弹窗
const handleAdd = (parentMenu?: Menu) => {
  dialogType.value = 'add'
  dialogTitle.value = parentMenu ? '新增子菜单' : '新增菜单'

  if (menuFormRef.value) menuFormRef.value.resetFields()

  Object.assign(menuForm, {
    menuId: '',
    menuName: '',
    parentId: parentMenu ? parentMenu.menuId : '0',
    path: '',
    component: '',
    permission: '',
    menuType: 'M',
    icon: '',
    orderNum: 0,
    menuFlag: '1'
  })

  dialogVisible.value = true
}

// 打开编辑弹窗
const handleEdit = (row: Menu) => {
  dialogType.value = 'edit'
  dialogTitle.value = '修改菜单'

  if (menuFormRef.value) menuFormRef.value.resetFields()

  getMenuById(row.menuId).then(res => {
    Object.assign(menuForm, res.data)
    dialogVisible.value = true
  }).catch(error => {
    ElMessage.error('获取菜单详情失败: ' + error.message)
  })
}

const loginStore = useLoginStore();


// 提交表单
const handleSubmit = () => {
  menuFormRef.value?.validate((valid) => {
    if (!valid) return

    formLoading.value = true
    const params = { ...menuForm }
    const request = dialogType.value === 'add' ? addMenu : updateMenu

    request(params).then(res => {
      ElMessage.success(res.msg || (dialogType.value === 'add' ? '新增成功' : '修改成功'))
      dialogVisible.value = false
      // 保存后重新加载数据，保持之前的展开状态
      const currentExpanded = [...expandedKeys.value]
      getMenusByCondition().then(() => {
        // 保持之前的展开状态
        expandedKeys.value = currentExpanded;
      })
      loadMenuTree()
      loginStore.triggerMenuRefresh();
    }).catch(error => {
      ElMessage.error(`${dialogType.value === 'add' ? '新增' : '修改'}失败: ${error.message}`)
    }).finally(() => {
      formLoading.value = false
    })
  })
}

// 删除菜单
const handleDelete = (menuId: number | string) => {
  confirmDelete(menuId)
}

// 批量删除
const handleBatchDelete = () => {
  if (multipleSelection.value.length > 0) {
    const ids = multipleSelection.value.map(item => item.menuId)
    confirmDelete(ids)
  }
}

// 确认删除
const confirmDelete = (ids: (number | string) | (number | string)[]) => {
  ElMessageBox.confirm(
    '确定要删除选中的菜单吗？删除后不可恢复',
    '警告',
    {
      confirmButtonText: '确认',
      cancelButtonText: '取消',
      type: 'warning'
    }
  ).then(() => {
    const request = Array.isArray(ids) ? deleteMenu(ids.join(',')) : deleteMenu(ids)
    request.then(res => {
      ElMessage.success('删除成功')
      // 删除后重新加载数据，清除已删除节点的展开状态
      if (Array.isArray(ids)) {
        expandedKeys.value = expandedKeys.value.filter(id => !ids.includes(id))
      } else {
        expandedKeys.value = expandedKeys.value.filter(id => id !== ids)
      }
      getMenusByCondition()
      loginStore.triggerMenuRefresh();
      loadMenuTree()
    }).catch(error => {
      ElMessage.error('删除失败: ' + error.message)
    })
  }).catch(() => {
    ElMessage.info('已取消删除')
  })
}

// 搜索
const handleSearch = () => {
  loading.value = true
  getMenusByCondition().finally(() => {
    loading.value = false
  })
}

// 重置
const handleReset = () => {
  query.menuName = ''
  query.menuFlag = ''
  query.menuType = ''
  loading.value = true
  getMenusByCondition().finally(() => {
    loading.value = false
  })
}

// 选择事件
const handleSelectionChange = (val: Menu[]) => {
  multipleSelection.value = val
}

// 表单验证规则
const rules = reactive<FormRules>({
  menuName: [
    { required: true, message: '请输入菜单名称', trigger: 'blur' },
    { min: 1, max: 50, message: '菜单名称长度需在1-50个字符之间', trigger: 'blur' }
  ],
  menuType: [
    { required: true, message: '请选择菜单类型', trigger: 'change' }
  ],
  orderNum: [
    { required: true, message: '请输入排序号', trigger: 'blur' },
    { type: 'number', min: 0, message: '排序号必须为非负整数', trigger: 'blur' }
  ],
  menuFlag: [
    { required: true, message: '请选择状态', trigger: 'change' }
  ],
  path: [
    {
      required: menuForm.menuType !== 'B',
      message: '请输入路由路径',
      trigger: 'blur'
    },
    { min: 1, max: 200, message: '路由路径长度需在1-200个字符之间', trigger: 'blur' }
  ],
  component: [
    {
      required: menuForm.menuType === 'M',
      message: '请输入组件路径',
      trigger: 'blur'
    },
    { min: 1, max: 200, message: '组件路径长度需在1-200个字符之间', trigger: 'blur' }
  ],
  icon: [
    {
      validator: (rule, value, callback) => {
        // 允许为空（可选图标），若有值则必须是预定义图标
        if (!value) return callback();
        if (iconNames.includes(value)) return callback();
        callback(new Error('请选择预定义的图标'));
      },
      trigger: 'change'
    }
  ]
})

// 监听菜单类型变化，动态更新验证规则
watch(() => menuForm.menuType, () => {
  if (menuFormRef.value) {
    menuFormRef.value.clearValidate(['path', 'component'])
  }
})


</script>

<style scoped>
.menu-page {
  width: 100%;
  background-color: #f0f2f5;
  min-height: calc(100vh - 48px);
}

.filter-card {
  margin-bottom: 20px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}

.el-card {
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
  overflow: hidden;
}

/* 树形节点缩进样式（只保留缩进，移除图标相关样式） */
.tree-indent {
  display: inline-flex;
  align-items: center;
  height: 100%;
}

/* 弹窗样式优化 */
.el-dialog__header {
  border-bottom: 1px solid #eee;
  padding: 16px 20px;
}

.el-dialog__body {
  padding: 20px;
}

.el-dialog__footer {
  border-top: 1px solid #eee;
  padding: 12px 20px;
}
</style>
